// *************************************
// * Creator:SunnyPaine
// * DateTime:2024/09/04 09:09:58
// * Description:<Description>
// * CopyRight:
// * ***********************************

using System;
using System.Collections.Generic;
using Autofac;
using Autofac.Core;

namespace SunnyPaine.Autofac.Extension.Mvvm.ViewCore
{
    /// <summary>
    /// 视图上下文容器。获取Window和Control的实例。
    /// </summary>
    public class ViewContext : IViewContext
    {
        private readonly IComponentContext _componentContext;
        private readonly Dictionary<string, IWindow> viewDict;


        /// <summary>
        /// 使用指定的参数创建 <see cref="ViewContext"/> 的实例。
        /// </summary>
        /// <param name="context">Autofac的IOC容器的组件上下文容器。</param>
        public ViewContext(IComponentContext context)
        {
            this._componentContext = context;
            this.viewDict = new Dictionary<string, IWindow>();
        }


        /// <summary>
        /// 获取视图实例。当视图已经存在，则返回它的单例，否则重新创建一个新的实例。
        /// </summary>
        /// <param name="name">视图的名称。</param>
        /// <returns>返回视图的实例。</returns>
        public IWindow Resolve(string name)
        {
            if (this.viewDict.ContainsKey(name))
            {
                return this.viewDict[name];
            }

            IWindow view = this._componentContext.ResolveNamed<IWindow>(name);
            view.Closed += (s, e) =>
            {
                if (this.viewDict.ContainsKey(name))
                {
                    this.viewDict.Remove(name);
                }
            };
            this.viewDict.Add(name, view);
            return view;
        }

        /// <summary>
        /// 获取视图实例。当视图已经存在，则返回它的单例，否则重新创建一个新的实例。
        /// </summary>
        /// <param name="name">视图的名称。</param>
        /// <param name="paras">
        /// 构造方法的参数。
        /// <para>注意：由于该方法获取视图是以单例模式执行，所以构造方法参数只有在第一次获取实例时会生效执行，从第二次获取实例开始，构造方法参数及时发生了变化也不再生效。</para>
        /// </param>
        /// <returns>返回视图的实例。</returns>
        public IWindow Resolve(string name, Tuple<string, object>[] paras)
        {
            if (this.viewDict.ContainsKey(name))
            {
                return this.viewDict[name];
            }

            List<Parameter> parameters = new List<Parameter>();
            foreach (Tuple<string, object> p in paras)
            {
                parameters.Add(new NamedParameter(p.Item1, p.Item2));
            }
            IWindow view = this._componentContext.ResolveNamed<IWindow>(name, parameters);
            view.Closed += (s, e) =>
            {
                if (this.viewDict.ContainsKey(name))
                {
                    this.viewDict.Remove(name);
                }
            };
            this.viewDict.Add(name, view);
            return view;
        }

        /// <summary>
        /// 获取视图实例。它将总是获取一个新的实例，而不是单例。
        /// </summary>
        /// <param name="name">视图的名称。</param>
        /// <returns>返回视图的实例，它将总是一个新的实例。</returns>
        public IWindow ResolveNew(string name)
        {
            return this._componentContext.ResolveNamed<IWindow>(name);
        }

        /// <summary>
        /// 获取视图实例。它将总是获取一个新的实例，而不是单例。
        /// </summary>
        /// <param name="name">视图的名称。</param>
        /// <param name="paras">构造方法的参数。</param>
        /// <returns>返回视图的实例，它将总是一个新的实例。</returns>
        public IWindow ResolveNew(string name, Tuple<string, object>[] paras)
        {
            List<Parameter> parameters = new List<Parameter>();
            foreach (Tuple<string, object> p in paras)
            {
                parameters.Add(new NamedParameter(p.Item1, p.Item2));
            }
            return this._componentContext.ResolveNamed<IWindow>(name, parameters);
        }

        /// <summary>
        /// 获取视图组件实例。它将总是获取一个新的实例，而不是单例。
        /// </summary>
        /// <param name="name">视图组件的名称。</param>
        /// <returns>返回视图组件实例。它将总是一个新的实例。</returns>
        public IControl ResolveControl(string name)
        {
            return this._componentContext.ResolveNamed<IControl>(name);
        }

        /// <summary>
        /// 获取视图组件实例。它将总是获取一个新的实例，而不是单例。
        /// </summary>
        /// <param name="name">视图组件的名称。</param>
        /// <param name="paras">构造方法的参数。</param>
        /// <returns>返回视图组件实例。它将总是一个新的实例。</returns>
        public IControl ResolveControl(string name, Tuple<string, object>[] paras)
        {
            List<Parameter> parameters = new List<Parameter>();
            foreach (Tuple<string, object> p in paras)
            {
                parameters.Add(new NamedParameter(p.Item1, p.Item2));
            }
            return this._componentContext.ResolveNamed<IControl>(name, parameters);
        }
    }
}